home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rsynth / src / hplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  9.4 KB  |  387 lines

  1. #ifdef SUN
  2. /*****************************************************************/
  3. /*****************************************************************/
  4. /***                                                           ***/
  5. /***                                                           ***/
  6. /***    Play out a 20kHz file on the SPARC                     ***/
  7. /***                                                           ***/
  8. /***                                                           ***/
  9. /***                H.F. Silverman 1/4/91                      ***/
  10. /***    Modified:   H.F. Silverman 1/16/91 for amax parameter  ***/
  11. /***    Modified:   A. Smith 2/14/91 for 8kHz for klatt synth  ***/
  12. /***                                                           ***/
  13. /*** Called: hplay(n,volume,amax,a)                            ***/
  14. /***                                                           ***/
  15. /***   int       n      -- No. of 8kHz pts.                    ***/
  16. /***   int    device    -- 0 -> speaker, 1 -> Jack             ***/
  17. /***                                                           ***/
  18. /***                                                           ***/
  19. /*****************************************************************/
  20. /*****************************************************************/
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <math.h>
  25. #include <errno.h>
  26. #include <ctype.h>
  27.  
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <sys/types.h>
  31. #include <sys/file.h>
  32. #include <sys/filio.h>
  33. #include <sys/stat.h>
  34. #include <sys/param.h>
  35. #include <sys/signal.h>
  36.  
  37. #include <stropts.h>
  38. #include <sys/ioctl.h>
  39.  
  40. #include <multimedia/libaudio.h>
  41. #include <multimedia/audio_device.h>
  42. #include <multimedia/ulaw2linear.h>
  43. #include "proto.h"
  44. #include "getargs.h"
  45. #include "hplay.h"
  46.  
  47. #define SAMP_RATE 8000
  48. long samp_rate = SAMP_RATE;
  49.  
  50. /* Audio Parameters */
  51.  
  52. int Verbose = FALSE;
  53.                                 /* verbose messages */
  54. int Immediate = FALSE;
  55.                                 /* Should we hang waiting for device ? */
  56.  
  57. static int async = TRUE;
  58.  
  59. static Audio_hdr dev_header;
  60.                                 /* audio header for device */
  61. static int dev_fd = -1;
  62.                                 /* file descriptor for audio device */
  63. char *dev_file = "/dev/audio";
  64.  
  65. static Audio_hdr ulaw_header;
  66.                                 /* audio header for file */
  67. static int ulaw_fd = -1;
  68.                                 /* file descriptor for .au ulaw file */
  69. static char *ulaw_file = NULL;
  70.  
  71. static int linear_fd = -1;
  72.  
  73. static int dev_kind = AUDIO_DEV_AMD;
  74.                                 /* file descriptor for 16 bit linear file */
  75. static char *linear_file = NULL;
  76.  
  77. char *prog = "hplay";
  78. char *Ifile;        /* current filename */
  79.  
  80. static void audio_catch
  81. PROTO((void))
  82. {
  83.  fprintf(stderr, "signal\n");
  84. }
  85.  
  86. static int audio_open
  87. PROTO((void))
  88. {
  89.  /* Try it quickly, first */
  90.  dev_fd = open(dev_file, O_WRONLY | O_NDELAY);
  91.  if ((dev_fd < 0) && (errno == EBUSY))
  92.   {
  93.    if (Immediate)
  94.     {
  95.      fprintf(stderr, "%s: %s is busy\n", prog, dev_file);
  96.      return 0;
  97.     }
  98.    if (Verbose)
  99.     {
  100.      fprintf(stderr, "%s: waiting for %s...", prog, dev_file);
  101.      (void) fflush(stderr);
  102.     }
  103.  
  104.    /* Now hang until it's open */
  105.  
  106.    dev_fd = open(dev_file, O_WRONLY);
  107.    if (Verbose)
  108.     fprintf(stderr, "%s\n", (dev_fd < 0) ? "" : "open");
  109.   }
  110.  if (dev_fd < 0)
  111.   {
  112.    fprintf(stderr, "%s: error opening ", prog);
  113.    perror(dev_file);
  114.    return 0;
  115.   }
  116.  else
  117.   {
  118.    /* Get the device output encoding configuration */
  119.    if (ioctl(dev_fd,AUDIO_GETDEV,&dev_kind))
  120.     {
  121.      /* Old releases of SunOs don't support the ioctl,
  122.         but can only be run on old machines which have AMD device...
  123.      */
  124.      dev_kind = AUDIO_DEV_AMD;
  125.     }
  126.    if (audio_get_play_config(dev_fd, &dev_header) != AUDIO_SUCCESS)
  127.     {
  128.      fprintf(stderr, "%s: %s is not an audio device\n", prog, dev_file);
  129.      close(dev_fd);
  130.      dev_fd = -1;
  131.      return 0;
  132.     }
  133.   }
  134.  return 1;
  135. }
  136.  
  137. int
  138. audio_init(argc, argv)
  139. int argc;
  140. char *argv[];
  141. {
  142.  int rate_set = 0;
  143.  int use_linear = 0;
  144.  int use_audio = 1;
  145.  double gain = -1.0;
  146.  int headphone = 2;
  147.  int speaker   = 2;
  148.  
  149.  prog = argv[0];
  150.  
  151.  argc = getargs(argc,argv,
  152.                 "g", "%lg", &gain,
  153.                 "r", "%d",  &rate_set,
  154.                 "h", NULL,  &headphone,
  155.                 "s", NULL,  &speaker,
  156.                 "a", NULL,  &use_audio,
  157.                 "L", NULL,  &use_linear,
  158.                 "u", "",    &ulaw_file,
  159.                 "l", "",    &linear_file,
  160.                 NULL);
  161.  
  162.  if (ulaw_file)
  163.   {
  164.    ulaw_fd = open(ulaw_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  165.    if (ulaw_fd < 0)
  166.     perror(ulaw_file);
  167.   }
  168.  
  169.  if (linear_file)
  170.   {
  171.    linear_fd = open(linear_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  172.    if (linear_fd < 0)
  173.     perror(linear_file);
  174.   }
  175.  
  176.  if (rate_set)
  177.   {
  178.    samp_rate = rate_set;
  179.   }
  180.  
  181.  if (use_audio && audio_open())
  182.   {
  183.    if (!rate_set)
  184.     samp_rate = dev_header.sample_rate;
  185.  
  186.    if (rate_set || use_linear)
  187.     {
  188.      dev_header.sample_rate = samp_rate;
  189.      if (samp_rate > 8000 || use_linear)
  190.       {
  191.        dev_header.encoding = AUDIO_ENCODING_LINEAR;
  192.        dev_header.bytes_per_unit = 2;
  193.       }
  194.      if (audio_set_play_config(dev_fd, &dev_header) != AUDIO_SUCCESS)
  195.       {
  196.        fprintf(stderr, "%s : %s cannot accept sample rate of %dHz\n",
  197.                prog, dev_file, samp_rate);
  198.        close(dev_fd);
  199.        dev_fd = -1;
  200.       }
  201.     }
  202.   }
  203.  if (dev_fd >= 0)
  204.   {int myport = 0;
  205.    if (gain >= 0.0)
  206.     {
  207.      int err = audio_set_play_gain(dev_fd, &gain);
  208.      if (err != AUDIO_SUCCESS)
  209.       {
  210.        fprintf(stderr, "%s: could not set output volume for %s\n", prog, dev_file);
  211.       }
  212.     }
  213.  
  214.    if (headphone != 2)
  215.     {
  216.      if (headphone)
  217.       myport |= AUDIO_HEADPHONE;
  218.      else
  219.       myport &= ~AUDIO_HEADPHONE;
  220.     }
  221.  
  222.    if (speaker != 2)
  223.     {
  224.      if (speaker)
  225.       myport |= AUDIO_SPEAKER;
  226.      else
  227.       myport &= ~AUDIO_SPEAKER;
  228.     }
  229.  
  230.    if (myport != 0)
  231.     audio_set_play_port(dev_fd, &myport);
  232.  
  233.    if (async)
  234.     {
  235.      int flag = 1;
  236.      /* May need to use streams calls to send a SIGPOLL when write
  237.         buffer is no longer full and use non-blocking writes, and
  238.         manipluate our own buffer of unwritten data.
  239.  
  240.         However, at present just use FIOASYNC which means write
  241.         returns as soon as it can queue the data (I think).
  242.      */
  243.      signal(SIGIO, audio_catch);
  244.      ioctl(dev_fd, FIOASYNC, &flag);
  245.     }
  246.   }
  247.  if (ulaw_fd >= 0)
  248.   {
  249.    ulaw_header.sample_rate = samp_rate;
  250.    if (samp_rate > 8000)
  251.     {
  252.      ulaw_header.encoding = AUDIO_ENCODING_LINEAR;
  253.      ulaw_header.bytes_per_unit = 2;
  254.     }
  255.    else
  256.     {
  257.      ulaw_header.encoding = AUDIO_ENCODING_ULAW;
  258.      ulaw_header.bytes_per_unit = 1;
  259.     }
  260.    ulaw_header.samples_per_unit = 1;
  261.    ulaw_header.channels = 1;
  262.    ulaw_header.data_size = 0;
  263.  
  264.    /* Write header - note that data_size is unknown at this stage,
  265.       if all goes well we will lseek back and do this again
  266.       in audio_term()
  267.    */
  268.    audio_write_filehdr(ulaw_fd, &ulaw_header, NULL, 0);
  269.   }
  270.  return argc;
  271. }
  272.  
  273. void
  274. audio_term()
  275. {
  276.  /* Close audio system  */
  277.  if (dev_fd >= 0)
  278.   {
  279.    audio_drain(dev_fd, FALSE);
  280.    close(dev_fd);
  281.    dev_fd = -1;
  282.    if (async)
  283.     signal(SIGPOLL, SIG_DFL);
  284.   }
  285.  
  286.  /* Finish ulaw file */
  287.  if (ulaw_fd >= 0)
  288.   {
  289.    off_t here = lseek(ulaw_fd, 0L, SEEK_CUR);
  290.    if (here >= 0)
  291.     {
  292.      /* can seek this file - truncate it */
  293.      ftruncate(ulaw_fd, here);
  294.  
  295.      /* Now go back and overwite header with actual size */
  296.      if (lseek(ulaw_fd, 0L, SEEK_SET) == 0)
  297.       {
  298.        audio_write_filehdr(ulaw_fd, &ulaw_header, NULL, 0);
  299.       }
  300.     }
  301.    close(ulaw_fd);
  302.    ulaw_fd = -1;
  303.   }
  304.  
  305.  /* Finish linear file */
  306.  if (linear_fd >= 0)
  307.   {
  308.    ftruncate(linear_fd, lseek(linear_fd, 0L, SEEK_CUR));
  309.    close(linear_fd);
  310.    linear_fd = -1;
  311.   }
  312. }
  313.  
  314. void
  315. audio_play(n, data)
  316. int n;
  317. short *data;
  318. {
  319.  if (n > 0)
  320.   {
  321.    if (linear_fd >= 0)
  322.     {
  323.      unsigned size = n * sizeof(short);
  324.      if (write(linear_fd, data, n * sizeof(short)) != size)
  325.             perror("write");
  326.     }
  327.  
  328.    if (dev_fd >= 0 && dev_header.encoding == AUDIO_ENCODING_LINEAR)
  329.     {
  330.      unsigned size = n * sizeof(short);
  331.      if (write(dev_fd, data, n * sizeof(short)) != size)
  332.             perror("write");
  333.     }
  334.  
  335.    if (ulaw_fd >= 0 && ulaw_header.encoding == AUDIO_ENCODING_LINEAR)
  336.     {
  337.      unsigned size = n * sizeof(short);
  338.      if (write(ulaw_fd, data, n * sizeof(short)) != size)
  339.             perror("write");
  340.      else
  341.       ulaw_header.data_size += size;
  342.     }
  343.  
  344.    if ((dev_fd  >= 0 && dev_header.encoding == AUDIO_ENCODING_ULAW) ||
  345.        (ulaw_fd >= 0 && ulaw_header.encoding == AUDIO_ENCODING_ULAW))
  346.     {
  347.      unsigned char *plabuf = (unsigned char *) malloc(n);
  348.      if (plabuf)
  349.       {
  350.        int w;
  351.        unsigned char *p = plabuf;
  352.        unsigned char *e = p + n;
  353.        while (p < e)
  354.         {
  355.          *p++ = audio_s2u(*data++);
  356.         }
  357.        if (dev_fd >= 0 && dev_header.encoding == AUDIO_ENCODING_ULAW)
  358.         {
  359.          if ((w = write(dev_fd, plabuf, n)) != n)
  360.           {
  361.            if (w == -1)
  362.             perror("audio");
  363.            else
  364.             {
  365.              fprintf(stderr, "Writing %u, only wrote %u\n", n, w);
  366.             }
  367.            abort();
  368.           }
  369.         }
  370.        if (ulaw_fd >= 0 && ulaw_header.encoding == AUDIO_ENCODING_ULAW)
  371.         {
  372.          if (write(ulaw_fd, plabuf, n) != n)
  373.           perror(ulaw_file);
  374.          else
  375.           ulaw_header.data_size += n;
  376.         }
  377.        free(plabuf);
  378.       }
  379.      else
  380.       {
  381.        fprintf(stderr, "%s : No memory for ulaw data\n", prog);
  382.       }
  383.     }
  384.   }
  385. }
  386. #endif
  387.